package com.jiangyg.mall.db.mybatis.metadata;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.jiangyg.mall.core.support.restful.Order;
import com.jiangyg.mall.core.support.restful.Pagination;
import com.jiangyg.mall.core.utils.HumpUtils;
import com.jiangyg.mall.core.utils.bean.BeanUtils;
import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 类描述：分页信息
 *
 * @author jiangyg
 * @version 2.0
 * @date 2020-01-03
 */
public class Pager<T> implements IPage<T> {

    private static final long serialVersionUID = 3878704383315621613L;

    /**
     * 查询数据列表
     */
    private List<T> records = Collections.emptyList();

    /**
     * 总数
     */
    private long total = 0;

    /**
     * 每页显示条数，默认 10
     */
    private long size = 10;

    /**
     * 当前页
     */
    private long current = 1;

    /**
     * 排序字段信息
     */
    private List<OrderItem> orders = new ArrayList<>();

    /**
     * 自动优化 COUNT SQL
     */
    private boolean optimizeCountSql = true;

    /**
     * 是否进行 count 查询
     */
    private boolean isSearchCount = true;

    /**
     * 是否命中count缓存
     */
    private boolean hitCount = false;

    public Pager() {
        super();
    }

    @Override
    public List<OrderItem> orders() {
        return this.orders;
    }

    public List<OrderItem> getOrders() {
        return orders;
    }

    public void setOrders(List<OrderItem> orders) {
        this.orders = orders;
    }

    @Override
    public List<T> getRecords() {
        return this.records;
    }

    @Override
    public Pager<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    @Override
    public long getTotal() {
        return this.total;
    }

    @Override
    public Pager<T> setTotal(long total) {
        this.total = total;
        return this;
    }

    @Override
    public long getSize() {
        return this.size;
    }

    @Override
    public Pager<T> setSize(long size) {
        this.size = size;
        return this;
    }

    @Override
    public long getCurrent() {
        return this.current;
    }

    @Override
    public Pager<T> setCurrent(long current) {
        this.current = current;
        return this;
    }

    @Override
    public boolean optimizeCountSql() {
        return optimizeCountSql;
    }

    public boolean isOptimizeCountSql() {
        return optimizeCountSql();
    }

    @Override
    public boolean isSearchCount() {
        if (total < 0) {
            return false;
        }
        return isSearchCount;
    }

    public Pager<T> setSearchCount(boolean isSearchCount) {
        this.isSearchCount = isSearchCount;
        return this;
    }

    public Pager<T> setOptimizeCountSql(boolean optimizeCountSql) {
        this.optimizeCountSql = optimizeCountSql;
        return this;
    }

    @Override
    public void hitCount(boolean hit) {
        this.hitCount = hit;
    }

    public void setHitCount(boolean hit) {
        this.hitCount = hit;
    }

    @Override
    public boolean isHitCount() {
        return hitCount;
    }

    /**
     * 功能描述：是否存在上一页
     *
     * @return 返回boolean
     */
    public boolean hasPrevious() {
        return this.current > 1;
    }

    /**
     * 功能描述：是否存在下一页
     *
     * @return 返回boolean
     */
    public boolean hasNext() {
        return this.current < this.getPages();
    }

    /**
     * 功能描述：添加新的排序条件，构造条件可以使用工厂：OrderItem.build(String, boolean)
     *
     * @param items 条件
     * @return 返回分页参数本身
     */
    public Pager<T> addOrder(OrderItem... items) {
        orders.addAll(Arrays.asList(items));
        return this;
    }

    /**
     * 功能描述：添加新的排序条件，构造条件可以使用工厂：OrderItem.build(String, boolean)
     *
     * @param items 条件
     * @return 返回分页参数本身
     */
    public Pager<T> addOrder(List<OrderItem> items) {
        orders.addAll(items);
        return this;
    }

    /**
     * 功能描述：Pagination转Pager类型的分页对象
     */
    public static <T> Pager<T> from(Pagination<?> pagination) {
        final Pager<T> pager = new Pager<>();
        pager.setSize(pagination.getSize());
        pager.setCurrent(pagination.getCurrent());
        // 排序
        List<Order> orders = pagination.getOrders();
        if (CollectionUtils.isNotEmpty(orders)) {
            orders.forEach(order -> {
                String column = HumpUtils.camelToUnderline(order.getName());
                OrderItem item = new OrderItem();
                item.setColumn(column);
                item.setAsc(order.isAsc());
                pager.addOrder(item);
            });
        }
        return pager;
    }

    /**
     * 功能描述：转换 Pagination 类型
     *
     * @param clazz 类型
     * @return 返回分页对象
     */
    public <V> Pagination<V> toPagination(Class<V> clazz) throws Exception {
        final Pagination<V> pagination = new Pagination<>();
        pagination.setRecords(BeanUtils.transformList(this.getRecords(), clazz));
        pagination.setTotal(this.getTotal());
        pagination.setCurrent(this.getCurrent());
        pagination.setSize(this.getSize());
        return pagination;
    }

    @Override
    public String toString() {
        return BeanUtils.toString(this);
    }

}
